#include "ASProgressBar.h"

#define ROUND_RECT_CORNER_WIDTH 3

static as_ret as_ctrl_progressbar_set_percent(as_control* ctrl_p, ASINT percent)
{
    as_progressbar* progress_p = (as_progressbar*)ctrl_p;

    if(!progress_p)
        return AS_INVALID_PARAM;

    if(progress_p->percent == percent)
        return AS_IGNORE;

    if(percent < 0)
        percent = 0;

    if(percent > 100)
        percent = 100;

    progress_p->percent = percent;
    return AS_OK;
}

static as_ret as_ctrl_progressbar_update(as_control* ctrl_p)
{
    if(!ctrl_p)
        return AS_INVALID_PARAM;

    ctrl_p->paint_hdlr(ctrl_p);
    as_ctrl_flush();
    return AS_OK;
}

static as_ret as_ctrl_progressbar_set_bg_frame_color(as_control* ctrl_p, ASINT color)
{
    as_progressbar* progress_p = (as_progressbar*)ctrl_p;

    if(!progress_p)
        return AS_INVALID_PARAM;

    progress_p->bg_frame_color = color;
    return AS_OK;
}

static as_ret as_ctrl_progressbar_set_bg_fill_color(as_control* ctrl_p, ASINT color)
{
    as_progressbar* progress_p = (as_progressbar*)ctrl_p;

    if(!progress_p)
        return AS_INVALID_PARAM;

    progress_p->bg_fill_color = color;
    return AS_OK;
}

static as_ret as_ctrl_progressbar_set_fg_color(as_control* ctrl_p, ASINT color_cnts, ASINT* colors)
{
    as_progressbar* progress_p = (as_progressbar*)ctrl_p;
    ASINT i = 0;

    if(!progress_p || color_cnts > AS_BAR_FILL_COLOR_MAX_CNTS)
        return AS_INVALID_PARAM;

    progress_p->fg_fill_color_counts = color_cnts;

    for(i = 0; i < progress_p->fg_fill_color_counts; i++)
    {
        progress_p->fg_fill_colors[i] = *(colors + i);
    }

    return AS_OK;
}

static as_ret as_ctrl_progressbar_set_bg_img(as_control* ctrl_p, ASWSTR tail_path,
        ASWSTR tile_path, as_image_src_type type)
{
    as_progressbar* progress_p = (as_progressbar*)ctrl_p;

    if(!progress_p || !tail_path || !tile_path)
        return AS_INVALID_PARAM;

    progress_p->bg_tail_img = as_ctrl_image_create(progress_p->base.area,
                              type, tail_path, FALSE);
    progress_p->bg_tile_img = as_ctrl_image_create(progress_p->base.area,
                              type, tile_path, FALSE);

    if(progress_p->bg_tail_img && progress_p->bg_tile_img)
    {
        progress_p->bg_tile_img->set_show_type((as_control*)progress_p->bg_tile_img, AS_IMAGE_TILED);
        return AS_OK;
    }
    else
    {
        as_ctrl_destroy((as_control*)progress_p->bg_tail_img);
        as_ctrl_destroy((as_control*)progress_p->bg_tile_img);
        return AS_MEMORY_NOT_ENOUGH;
    }
}

static as_ret as_ctrl_progressbar_set_fg_img(as_control* ctrl_p, ASWSTR tail_path,
        ASWSTR tile_path, as_image_src_type type)
{
    as_progressbar* progress_p = (as_progressbar*)ctrl_p;

    if(!progress_p || !tail_path || !tile_path)
        return AS_INVALID_PARAM;

    progress_p->fg_tail_img = as_ctrl_image_create(progress_p->base.area,
                              type, tail_path, FALSE);
    progress_p->fg_tile_img = as_ctrl_image_create(progress_p->base.area,
                              type, tile_path, FALSE);

    if(progress_p->fg_tail_img && progress_p->fg_tile_img)
    {
        progress_p->fg_tile_img->set_show_type((as_control*)progress_p->fg_tile_img, AS_IMAGE_TILED);
        return AS_OK;
    }
    else
    {
        as_ctrl_destroy((as_control*)progress_p->fg_tail_img);
        as_ctrl_destroy((as_control*)progress_p->fg_tile_img);
        return AS_MEMORY_NOT_ENOUGH;
    }
}

static as_ret as_ctrl_progressbar_set_valid_area(as_control* ctrl_p, as_rect valid_area)
{
    as_progressbar* progress_p = (as_progressbar*)ctrl_p;

    if(!progress_p)
        return AS_INVALID_PARAM;

    memcpy(&progress_p->valid_show_area, &valid_area, sizeof(as_rect));
    return AS_OK;
}

#if 0
static ASINT as_ctrl_get_offset_in_circle(ASINT max_w, ASINT max_h, ASINT min_h, ASINT cur_h)
{
    ASINT _max = max_h - min_h;
    ASINT _cur = cur_h - min_h;
    ASINT _half = _max >> 1;
    ASINT _off = 0;

    if(_cur <= _half * 0.134)
    {
        _off = (max_w >> 1) * _cur / (_half * 0.134);
    }
    else if(_cur <= _half / 2)
    {
    }
    else if(_cur <= _half)
    {
    }
    else if(_cur - _half <= _half / 2)
    {
    }
    else if(_cur - _half <= _half * 0.866)
    {
    }
    else
    {
    }

    return _off;
}
#endif

static void as_ctrl_progressbar_paint_type_color(as_progressbar* progress_p)
{
    as_rect* area_p, clip;
    ASINT layer;
    ASUINT8* paint_buf;

    if(!progress_p)
        return;

    area_p = &progress_p->base.area;
    layer = progress_p->base.show_hdlr;
    paint_buf = as_get_layer_buffer_by_hdlr(layer);

    if(layer < 0 || as_set_layer_clip_ex(layer, area_p) == AS_IGNORE)
        return;

    memcpy(&clip, area_p, sizeof(as_rect));
    as_draw_rect(&clip, progress_p->bg_frame_color);
    clip.x++;
    clip.y++;
    clip.w -= 2;
    clip.h -= 2;
    as_fill_rect(&clip, progress_p->bg_fill_color, progress_p->bg_fill_color);
    clip.x++;
    clip.y++;
    clip.w -= 2;
    clip.h -= 2;
    clip.w = (ASINT16)(clip.w * progress_p->percent / 100);

    if(clip.w > 0 && progress_p->fg_fill_color_counts > 0)
    {
        as_fill_rect(&clip, progress_p->fg_fill_colors[0], progress_p->fg_fill_colors[0]);
    }

    as_reset_layer_clip(layer);
}

static void as_ctrl_progress_paint_bar_type_img(ASINT layer, as_rect valid_area , as_rect paint_area, as_rect ref_area,
        as_image* tail_img, as_image* tile_img)
{
    /*left half tail*/
    paint_area.w = tail_img->img_w / 2;
    as_set_layer_clip_ex(layer, &valid_area);

    if(as_set_layer_clip_ex(layer, &paint_area) == AS_IGNORE)
        return;

    tail_img->base.change_area_hdlr((as_control*)tail_img, paint_area);
    tail_img->base.paint_hdlr((as_control*)tail_img);
    as_reset_layer_clip(layer);
    /*tile part*/
    paint_area.x += (ASINT16)(tail_img->img_w >> 1);
    paint_area.w = ref_area.w - tail_img->img_w;
    tile_img->base.change_area_hdlr((as_control*)tile_img, paint_area);
    as_set_layer_clip_ex(layer, &valid_area);

    if(as_set_layer_clip_ex(layer, &paint_area) == AS_IGNORE)
        return;

    tile_img->base.paint_hdlr((as_control*)tile_img);
    as_reset_layer_clip(layer);
    /*right half tail*/
    paint_area.x += paint_area.w;
    paint_area.w = tail_img->img_w / 2;
    as_set_layer_clip_ex(layer, &valid_area);

    if(as_set_layer_clip_ex(layer, &paint_area) == AS_IGNORE)
        return;

    paint_area.x -= paint_area.w;
    paint_area.w += paint_area.w;
    tail_img->base.change_area_hdlr((as_control*)tail_img, paint_area);
    tail_img->base.paint_hdlr((as_control*)tail_img);
}

static void as_ctrl_progressbar_paint_type_image(as_progressbar* progress_p)
{
    as_rect area, ref_area;
    ASINT layer = progress_p->base.show_hdlr;
    //paint bg first
    memcpy(&area, &progress_p->base.area, sizeof(as_rect));
    memcpy(&ref_area, &area, sizeof(as_rect));
    as_ctrl_progress_paint_bar_type_img(layer, progress_p->valid_show_area , area, ref_area,
                                        progress_p->bg_tail_img, progress_p->bg_tile_img);
    //paint fg second
    memcpy(&area, &progress_p->base.area, sizeof(as_rect));
    area.w = (ASINT16)(progress_p->base.area.w * progress_p->percent / 100);

    if(area.w > 0 && area.w < progress_p->fg_tail_img->img_w)
        area.w = progress_p->fg_tail_img->img_w;

    area.h = progress_p->fg_tail_img->img_h;
    area.y = progress_p->base.area.y + (progress_p->base.area.h - progress_p->fg_tail_img->img_h) / 2;
    area.x += 2;
    area.w -= 4;
    memcpy(&ref_area, &area, sizeof(as_rect));
    as_ctrl_progress_paint_bar_type_img(layer, progress_p->valid_show_area, area, ref_area,
                                        progress_p->fg_tail_img, progress_p->fg_tile_img);
}

static void as_ctrl_progressbar_paint(as_control* ctrl_p)
{
    as_progressbar* progress_p = (as_progressbar*)ctrl_p;

    if(!progress_p || ctrl_p->if_hidden)
        return;

    if(progress_p->type == AS_PB_TYPE_COLOR)
    {
        as_ctrl_progressbar_paint_type_color(progress_p);
    }
    else if(progress_p->type == AS_PB_TYPE_IMAGE)
    {
        as_ctrl_progressbar_paint_type_image(progress_p);
    }
    else
    {
        //warn
    }
}

as_progressbar* as_ctrl_progressbar_create(as_rect area, as_progressbar_type type)
{
    as_progressbar* progress_p = NULL;

    if(type < AS_PB_TYPE_COLOR || type >= AS_PB_TYPE_MAX)
        return NULL;

    progress_p = as_calloc(sizeof(as_progressbar));

    if(!progress_p)
        return NULL;

    as_ctrl_init((as_control*)progress_p, area);
    progress_p->base.paint_hdlr = as_ctrl_progressbar_paint;
    progress_p->base.ctrl_type = AS_CTRL_PROGRESSBAR;
    progress_p->type = type;
    progress_p->percent = 0;
    progress_p->set_percent = as_ctrl_progressbar_set_percent;
    progress_p->update = as_ctrl_progressbar_update;
    progress_p->set_bg_img = as_ctrl_progressbar_set_bg_img;
    progress_p->set_fg_img = as_ctrl_progressbar_set_fg_img;
    progress_p->set_bg_frame_color = as_ctrl_progressbar_set_bg_frame_color;
    progress_p->set_bg_fill_color = as_ctrl_progressbar_set_bg_fill_color;
    progress_p->set_fg_color = as_ctrl_progressbar_set_fg_color;
    progress_p->set_valid_area = as_ctrl_progressbar_set_valid_area;
    progress_p->set_valid_area((as_control*)progress_p, area);
    return progress_p;
}

as_ret as_ctrl_progressbar_destory(as_progressbar* progress_p)
{
    if(!progress_p)
        return AS_INVALID_PARAM;

    if(progress_p->type == AS_PB_TYPE_IMAGE)
    {
        if(progress_p->bg_tail_img)
        {
            as_ctrl_image_destroy(progress_p->bg_tail_img);
            progress_p->bg_tail_img = NULL;
        }

        if(progress_p->bg_tile_img)
        {
            as_ctrl_image_destroy(progress_p->bg_tile_img);
            progress_p->bg_tile_img = NULL;
        }

        if(progress_p->fg_tail_img)
        {
            as_ctrl_image_destroy(progress_p->fg_tail_img);
            progress_p->fg_tail_img = NULL;
        }

        if(progress_p->fg_tile_img)
        {
            as_ctrl_image_destroy(progress_p->fg_tile_img);
            progress_p->fg_tile_img = NULL;
        }
    }

    as_free(progress_p);
    progress_p = NULL;
    return AS_OK;
}